#!/usr/bin/perl
#####################################
# obj2sc v0.21                      #
# Converts binary to shellcode      #
# by x0rz <hourto_c@epita.fr>       #
#                                   #
# http://code.google.com/p/obj2sc/  #
#####################################

use Term::ANSIColor;
use Getopt::Long;
use Switch;

# Options
my $binary = "";
my $commented = 0;

GetOptions ('binary=s' => \$binary,
	    'commented' => \$commented,
	    'help' => sub { helpmessage() },
	    'version' => sub { helpmessage() });


sub usage
{
    return "usage: ./obj2sc.pl -b binary [-c -h]\n";
}

sub helpmessage
{
    print_comm ("obj2sc v0.21\n");
    print_comm ("by x0rz <hourto_c\@epita.fr>\n");
    print_comm ("http://code.google.com/p/obj2sc/\n");
    print_comm ("\n");
    print_comm (&usage());
    exit 0;
}


if ($binary eq "")
{
    print_comm (&usage());
    exit 1;
}



print_comm ("Converting `".$binary."' into shellcode...\n");

# Check if objdump exists
my $objdump_check = `objdump --version 2> /dev/null`;
if ($objdump_check eq "")
{
    print_ko();
    print("Couldn't load objdump\n");
    exit 1;
}

# Load objdump output
my $objdump = `objdump -d $binary 2> /dev/null`;
if ($objdump eq "")
{
    print_ko();
    print("Failed loading `$binary'\n");
    exit 1;
}

@lines = split(/\n/, $objdump);

my $sc = "";
my @opcodes;


foreach $line (@lines)
{
    $comments = $line;

    # is it an opcodes line?
    if ($line =~ m!^[ ]*[0-9a-f]*:.*$!i)
    {
	# cut everything to get what's needed
	$comments =~ s!.*\t(.*)$!\1!i;
	$line =~ s!^[ ]*[0-9a-f]*:\s+(.*)\t.*$!\1!i;

       	# add opcodes to the list
	push @opcodes, split(/\s+/, $line);


	if ($commented)
	{
	    #print "\"".$line . "\"\n";
	    $line =~ s/\s+$//;
	    $line =~ s/\s+/\\x/g;

	    my $tab = "";
	    switch (length($line))
	    {
		case [1..4]	{$tab = "\t\t\t"}
		case [5..12]	{$tab = "\t\t"}
		else		{$tab = "\t"}
	    }
	    print "\t\"\\x".$line . "\"".$tab."// " .$comments. "\n";
	}



	$sc .= $line;
    }
}

if ($commented)
{
    print_comm ("Plain shellcode below:\n");
}

# printing shellcode
my $zeroes = 0;
foreach $opcode (@opcodes)
{
    if ($opcode eq "00")
    {
	++$zeroes;
	print color 'red';
	print "\\x".$opcode;
	print color 'reset';
    }
    else
    {
	print "\\x".$opcode;
    }
}

print "\n";

if ($zeroes != 0)
{
    print_comm ("Warning: you've got $zeroes zero(s).\n");
}


print_ok();
print "Successfully generated shellcode (".scalar(@opcodes)." bytes).\n";


# Misc
sub print_ok {
    print color 'bold white';
    print "[";
    print color 'green';
    print "OK";
    print color 'white';
    print "] ";
    print color 'reset';
}

sub print_ko {
    print color 'bold white';
    print "[";
    print color 'red';
    print "KO";
    print color 'white';
    print "] ";
    print color 'reset';
}

sub print_info {
    print color 'bold white';
    print "[";
    print color 'blue';
    print ">>";
    print color 'white';
    print "] ";
    print color 'reset';
}

sub print_comm {
    print color 'bold red';
    print "# ";

    if (!((defined $_[1]) && $_[1] == "bold"))
    {
	print color 'reset';
    }

    print color 'yellow';
    print $_[0];
    print color 'reset';
}
